#include "uart/uart_hal.h"
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_uart.h"
#include "stm32f429xx.h"
#include "usart.h"

typedef struct stm32_hal_uart{
    UART_HandleTypeDef *uart;
}stm32_hal_uart_t;

typedef struct stm32_uart_map{
    const char *name;
    const char *use_type;
    stm32_hal_uart_t uart;
    uart_device_port_t port;
}stm32_uart_map_t;


static const stm32_uart_map_t stm32_uart_map_table[] = {
    {"UART2","UART", {.uart = &huart2}, .port = UART_PORT_0},
};


static const stm32_uart_map_t *get_stm32_gpio_map_entry(uart_device_port_t port) {
    const int port_map_num = DEVICE_ARRAY_SIZE(stm32_uart_map_table);
    for (int i = 0; i < port_map_num; i++) {
        if (stm32_uart_map_table[i].port == port) {
            return &stm32_uart_map_table[i];
        }
    }

    return NULL;
}
static const stm32_uart_map_t *get_stm32_gpio_map_entry_by_handle(UART_HandleTypeDef *uart) {
    const int port_map_num = DEVICE_ARRAY_SIZE(stm32_uart_map_table);
    for (int i = 0; i < port_map_num; i++) {
        if (stm32_uart_map_table[i].uart.uart == uart) {
            return &stm32_uart_map_table[i];
        }
    }

    return NULL;
}
/* 辅助：将 uart_device_data_bits_t/parity/stop/flow 转为 HAL 常量 */
static uint32_t to_hal_word_length(uart_device_data_bits_t dbits, uart_device_parity_t parity) {
    /* STM32F4 HAL: UART_WORDLENGTH_8B / UART_WORDLENGTH_9B
       当使用 9 数据位时选 9B；否则用 8B（即 5~8 全用 8B，若 parity 存在，HAL 内部会处理） */
    if (dbits == UART_DATA_BITS_9) {
        return UART_WORDLENGTH_9B;
    }
    return UART_WORDLENGTH_8B;
}

static uint32_t to_hal_parity(uart_device_parity_t p) {
    switch (p) {
        case UART_DATA_PARITY_NONE: return UART_PARITY_NONE;
        case UART_DATA_PARITY_EVEN: return UART_PARITY_EVEN;
        case UART_DATA_PARITY_ODD:  return UART_PARITY_ODD;
        default: return UART_PARITY_NONE;
    }
}

static uint32_t to_hal_stopbits(uart_device_stop_bits_t s) {
    switch (s) {
        case UART_STOP_BITS_1:   return UART_STOPBITS_1;
        case UART_STOP_BITS_2:   return UART_STOPBITS_2;
        default: return UART_STOPBITS_1;
    }
}

static uint32_t to_hal_flowctrl(uart_device_flow_control_t f) {
    switch (f) {
        case UART_FLOW_CTRL_NONE:      return UART_HWCONTROL_NONE;
        case UART_FLOW_CTRL_RTS:       return UART_HWCONTROL_RTS;
        case UART_FLOW_CTRL_CTS:       return UART_HWCONTROL_CTS;
        case UART_FLOW_CTRL_RTS_CTS:   return UART_HWCONTROL_RTS_CTS;
        default: return UART_HWCONTROL_NONE;
    }
}

static IRQn_Type uart_instance_to_irqn(USART_TypeDef *instance) {
    if (instance == USART1)  return USART1_IRQn;
    if (instance == USART2)  return USART2_IRQn;
    if (instance == USART3)  return USART3_IRQn;
#if defined(USART4) || defined(UART4)
    if (instance == UART4)   return UART4_IRQn;
#endif
#if defined(UART5)
    if (instance == UART5)   return UART5_IRQn;
#endif
    if (instance == USART6)  return USART6_IRQn;
    /* 若有其他 UART/USART，按需补充 */
    return (IRQn_Type)0; /* invalid */
}

int stm32_hal_uart_init(uart_device_port_t port, uart_device_config_t *cfg) {
    if (!cfg) return -1;
    const stm32_uart_map_t *map = get_stm32_gpio_map_entry(port);
    if (!map) return -2;
    UART_HandleTypeDef *huart = map->uart.uart;
    if (!huart) return -3;

    /* 填充 huart->Init */
    huart->Init.BaudRate = (uint32_t)cfg->baudrate;
    huart->Init.WordLength = to_hal_word_length(cfg->databits, cfg->parity);
    huart->Init.StopBits = to_hal_stopbits(cfg->stopbits);
    huart->Init.Parity = to_hal_parity(cfg->parity);
    huart->Init.HwFlowCtl = to_hal_flowctrl(cfg->flowctrl);
    huart->Init.Mode = UART_MODE_TX_RX;
    huart->Init.OverSampling = UART_OVERSAMPLING_16; /* 默认 16 */

    if (HAL_UART_Init(huart) != HAL_OK) {
        return -4;
    }

    /* 默认先不开 NVIC 中断；用户通过 ioctl 打开 isr_enable */
    return 0;
}

int stm32_hal_uart_deinit(uart_device_port_t port) {
    const stm32_uart_map_t *map = get_stm32_gpio_map_entry(port);
    if (!map) return -1;
    UART_HandleTypeDef *huart = map->uart.uart;
    if (!huart) return -2;

    if (HAL_UART_DeInit(huart) != HAL_OK) {
        return -3;
    }

    /* 禁用 NVIC 中断（防止悬挂） */
    IRQn_Type irqn = uart_instance_to_irqn(huart->Instance);
    if (irqn) {
        HAL_NVIC_DisableIRQ(irqn);
    }

    return 0;
}

int stm32_hal_uart_transmit(uart_device_port_t port, void *data, uint32_t len) {
    const stm32_uart_map_t *map = get_stm32_gpio_map_entry(port);
    if (!map) return -1;
    UART_HandleTypeDef *huart = map->uart.uart;
    if (!huart) return -2;

    HAL_UART_Transmit(huart, (uint8_t *)data, len, 1000);
    return 0;
}

int stm32_hal_uart_isr_enable(uart_device_port_t port) {
    const stm32_uart_map_t *map = get_stm32_gpio_map_entry(port);
    if (!map) return -1;
    UART_HandleTypeDef *huart = map->uart.uart;
    if (!huart) return -2;

    /* 使能接收中断（接收非空）和错误中断 */
    __HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
    __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
    __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

    /* 使能 NVIC（优先级根据工程需求调整） */
    IRQn_Type irqn = uart_instance_to_irqn(huart->Instance);
    if (irqn) {
        HAL_NVIC_SetPriority(irqn, 5, 0); /* 优先级可按需修改 */
        HAL_NVIC_EnableIRQ(irqn);
    }

    return 0;
}

/* hal_uart_isr_disable：禁用中断位与 NVIC */
int stm32_hal_uart_isr_disable(uart_device_port_t port) {
    const stm32_uart_map_t *map = get_stm32_gpio_map_entry(port);
    if (!map) return -1;
    UART_HandleTypeDef *huart = map->uart.uart;
    if (!huart) return -2;

    __HAL_UART_DISABLE_IT(huart, UART_IT_IDLE);
    __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
    __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

    IRQn_Type irqn = uart_instance_to_irqn(huart->Instance);
    if (irqn) {
        HAL_NVIC_DisableIRQ(irqn);
    }

    return 0;
}



void uart_hal_isr_received_handler(void *uart) {
    static uint16_t buffer_index = 0;
    static uint8_t uart_temp_buffer[512] = {0};
    UART_HandleTypeDef * uart_handle = uart;
    if (__HAL_UART_GET_FLAG(uart_handle, UART_FLAG_RXNE) == SET) {
        if (buffer_index >= sizeof(uart_temp_buffer)) {
            buffer_index = 0;
        }
        uart_temp_buffer[buffer_index ++] = uart_handle->Instance->DR & 0x1FF;
    }
    if (__HAL_UART_GET_FLAG(uart_handle, UART_FLAG_IDLE) == SET) {
        const stm32_uart_map_t *map = get_stm32_gpio_map_entry_by_handle(uart_handle);
        if (map) {
            uart_driver_isr_received_handler(map->port, uart_temp_buffer, buffer_index);
        }
        buffer_index = 0;
        __HAL_UART_CLEAR_IDLEFLAG(uart_handle);
    }
}

const uart_hal_driver_ops_t uart_hal_driver_stm32 = {
    .hal_uart_deinit = stm32_hal_uart_deinit,
    .hal_uart_init = stm32_hal_uart_init,
    .hal_uart_isr_disable = stm32_hal_uart_isr_disable,
    .hal_uart_isr_enable = stm32_hal_uart_isr_enable,
    .hal_uart_transmit = stm32_hal_uart_transmit,
};

